Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(core): Implement 3ds decision manger for V2 #7022

Open
wants to merge 15 commits into
base: main
Choose a base branch
from

Conversation

swangi-kumari
Copy link
Contributor

@swangi-kumari swangi-kumari commented Jan 10, 2025

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

  • Implement 3ds decision manger for V2
  • Merchant can configure different 3ds rule for each profile.

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

How did you test it?

  1. Organization Create
curl --location 'http://localhost:8080/v2/organization' \
--header 'Content-Type: application/json' \
--header 'api-key: test_admin' \
--data '{
    "organization_name": "random_org_1736926299"
}'
  1. Merchant Account Create
curl --location 'http://localhost:8080/v2/merchant-accounts' \
--header 'x-organization-id: org_ojPeFJQSwbmYHFykF4Md' \
--header 'Content-Type: application/json' \
--header 'api-key: test_admin' \
--data '{
    "merchant_name": "cloth_seller"
}'
  1. Business Profile Create
curl --location 'http://localhost:8080/v2/profiles' \
--header 'x-merchant-id: cloth_seller_PXTsb0I3Zu2n8E5xWRUD' \
--header 'Content-Type: application/json' \
--header 'api-key: test_admin' \
--data-raw '{
    "profile_name": "business",
    "return_url": "https://google.com/success",
    "enable_payment_response_hash": true,
    "redirect_to_merchant_with_http_post": false,
    "webhook_details": {
        "webhook_version": "1.0.1",
        "webhook_username": "ekart_retail",
        "webhook_password": "password_ekart@123",
        "webhook_url": "https://webhook.site",
        "payment_created_enabled": true,
        "payment_succeeded_enabled": true,
        "payment_failed_enabled": true
    },
    "metadata": null,
    "order_fulfillment_time": 900,
    "order_fulfillment_time_origin": "create",
    "applepay_verified_domains": null,
    "session_expiry": 900,
    "payment_link_config": null,
    "authentication_connector_details": null,
    "use_billing_as_payment_method_billing": true,
    "collect_shipping_details_from_wallet_connector_if_required": false,
    "collect_billing_details_from_wallet_connector_if_required": false,
    "always_collect_shipping_details_from_wallet_connector": false,
    "always_collect_billing_details_from_wallet_connector": false,
    "is_connector_agnostic_mit_enabled": false,
    "payout_link_config": null,
    "outgoing_webhook_custom_http_headers": null
}'
  1. Configure 3ds Rule to that Profile
curl --location --request PUT 'http://localhost:8080/v2/profiles/pro_RuygLuNPMy2PCqcEW96n/decision' \
--header 'x-merchant-id: cloth_seller_PXTsb0I3Zu2n8E5xWRUD' \
--header 'X-Profile-Id: pro_RuygLuNPMy2PCqcEW96n' \
--header 'Content-Type: application/json' \
--header 'api-key: dev_1rmHYg4vdeMtrq77KiCel53UBBoLzvKEfPQfWNQ4lTXTCm4S6Q3OP1uF9uiudmXZ' \
--data '{
    "name": "3DS Rule-2025-01-08",
    "program": {
        "defaultSelection": {
            "override_3ds": null
        },
        "rules": [
            {
                "name": "rule_1",
                "connectorSelection": {
                    "override_3ds": "three_ds"
                },
                "statements": [
                    {
                        "condition": [
                            {
                                "lhs": "amount",
                                "comparison": "equal",
                                "value": {
                                    "type": "number",
                                    "value": 32
                                },
                                "metadata": {}
                            },
                            {
                                "lhs": "currency",
                                "comparison": "equal",
                                "value": {
                                    "type": "enum_variant",
                                    "value": "AMD"
                                },
                                "metadata": {}
                            }
                        ]
                    }
                ]
            }
        ],
        "metadata": {}
    }
}'

Response

{
    "name": "3DS Rule-2025-01-08",
    "program": {
        "defaultSelection": {
            "override_3ds": null
        },
        "rules": [
            {
                "name": "rule_1",
                "connectorSelection": {
                    "override_3ds": "three_ds"
                },
                "statements": [
                    {
                        "condition": [
                            {
                                "lhs": "amount",
                                "comparison": "equal",
                                "value": {
                                    "type": "number",
                                    "value": 32
                                },
                                "metadata": {}
                            },
                            {
                                "lhs": "currency",
                                "comparison": "equal",
                                "value": {
                                    "type": "enum_variant",
                                    "value": "AMD"
                                },
                                "metadata": {}
                            }
                        ],
                        "nested": null
                    }
                ]
            }
        ],
        "metadata": {}
    },
    "created_at": 1736926264
}
  1. Retrive Business Profile
curl --location 'http://localhost:8080/v2/profiles/pro_RuygLuNPMy2PCqcEW96n/decision' \
--header 'x-merchant-id: cloth_seller_PXTsb0I3Zu2n8E5xWRUD' \
--header 'X-Profile-Id: pro_RuygLuNPMy2PCqcEW96n' \
--header 'api-key: dev_1rmHYg4vdeMtrq77KiCel53UBBoLzvKEfPQfWNQ4lTXTCm4S6Q3OP1uF9uiudmXZ'

Response

{
    "name": "3DS Rule-2025-01-08",
    "program": {
        "defaultSelection": {
            "override_3ds": null
        },
        "rules": [
            {
                "name": "rule_1",
                "connectorSelection": {
                    "override_3ds": "three_ds"
                },
                "statements": [
                    {
                        "condition": [
                            {
                                "lhs": "amount",
                                "comparison": "equal",
                                "value": {
                                    "type": "number",
                                    "value": 32
                                },
                                "metadata": {}
                            },
                            {
                                "lhs": "currency",
                                "comparison": "equal",
                                "value": {
                                    "type": "enum_variant",
                                    "value": "AMD"
                                },
                                "metadata": {}
                            }
                        ],
                        "nested": null
                    }
                ]
            }
        ],
        "metadata": {}
    },
    "created_at": 1736926264
}

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible

@swangi-kumari swangi-kumari added C-feature Category: Feature request or enhancement api-v2 labels Jan 10, 2025
@swangi-kumari swangi-kumari self-assigned this Jan 10, 2025
@swangi-kumari swangi-kumari requested review from a team as code owners January 10, 2025 10:06
Copy link

semanticdiff-com bot commented Jan 10, 2025

@hyperswitch-bot hyperswitch-bot bot added the M-database-changes Metadata: This PR involves database schema changes label Jan 10, 2025
@swangi-kumari swangi-kumari requested a review from a team as a code owner January 13, 2025 18:30
crates/router/src/core/conditional_config.rs Outdated Show resolved Hide resolved
crates/router/src/core/conditional_config.rs Outdated Show resolved Hide resolved
crates/router/src/core/routing/helpers.rs Outdated Show resolved Hide resolved
crates/common_utils/src/id_type/profile.rs Outdated Show resolved Hide resolved
crates/common_types/src/payments.rs Outdated Show resolved Hide resolved
let key_manager_state: &KeyManagerState = &(&state).into();
let profile_id = profile.get_id();

let profile = db
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we already have the profile in the params, we need not fetch the profile again

created_at: timestamp,
};

let business_profile_update = domain::ProfileUpdate::DecisionManagerRecordUpdate {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we need to clone the decision_manager_record here?

.attach_printable("Failed to update routing algorithm ref in business profile")?;

Ok(service_api::ApplicationResponse::Json(
decision_manager_record,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use the decision_manager_record from the profile, from profile update response

Narayanbhat166
Narayanbhat166 previously approved these changes Jan 27, 2025
apoorvdixit88
apoorvdixit88 previously approved these changes Jan 27, 2025
Copy link
Contributor

@apoorvdixit88 apoorvdixit88 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dashboard changes look fine.

#[derive(Serialize, Deserialize, Debug, Clone, FromSqlRow, AsExpression, ToSchema)]
#[diesel(sql_type = Jsonb)]
/// DecisionManagerRecord
pub struct DecisionManagerRecord {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We seem to be having a struct with the same name in the api_models crate as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have not reused the same struct as the one which is in api_models have a field called pub modified_at: i64, but for V2 we don't need that field.

Comment on lines 47 to 64
let updated_profile = db
.update_profile_by_profile_id(
key_manager_state,
&key_store,
profile,
business_profile_update,
)
.await
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to update routing algorithm ref in business profile")?;

Ok(service_api::ApplicationResponse::Json(
updated_profile
.three_ds_decision_manager_config
.clone()
.get_required_value("three_ds_decision_manager_config")
.change_context(errors::ApiErrorResponse::InternalServerError)
.attach_printable("Failed to get updated routing algorithm ref in business profile")?,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Failed to get updated routing algorithm ref in business profile

Are these error messages correct here?

let record = profile
.three_ds_decision_manager_config
.clone()
.ok_or_else(|| errors::ApiErrorResponse::InternalServerError)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can use ok_or() itself here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-v2 C-feature Category: Feature request or enhancement M-database-changes Metadata: This PR involves database schema changes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants